package cs348a.opengl.object;

import java.awt.Color;
import java.util.List;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;

import cs348a.color.*;
import cs348a.data.Edge;
import cs348a.data.EdgeFileData;
import cs348a.data.Site;
import cs348a.data.Triangle;

/**
 * <code>OpenGLSurface</code> is an <code>AbstractOpenGLObject</code> that draws a surface.
 * 
 * @author H.S Kim
 */
public class OpenGLSurface extends AbstractOpenGLObject{
	/** The site/edge data*/
	private EdgeFileData efData;
	
	/** The color transform */
	private PaletteModel paletteModel = new PaletteModel();
	
	/** The opacity of the surface */
	private float opacity = 0.8f;
	
	/** Show surface flag */
	private boolean showSurface = true;
	
	/**
	 * Constructor
	 * 
	 * @param efd
	 */
	public OpenGLSurface(EdgeFileData efd) {
		efData = efd;
		
		paletteModel.min = efData.minZ;
		paletteModel.max = efData.maxZ;
	}
	
	/**
	 * Sets the surface visible.
	 * 
	 * @param v
	 */
	public void setSurfaceVisible(boolean v) {
		showSurface = v;
	}
	
	/**
	 * Is the surface visible.
	 * 
	 * @return
	 */
	public boolean isSurfaceVisible() {
		return showSurface;
	}
	
	/**
	 * Sets the opacity
	 * 
	 * @param o
	 */
	public void opacity(float o) { 
		opacity = o;
	}
	
	/**
	 * Returns the opacity
	 * 
	 * @return
	 */
	public float opacity() {
		return opacity;
	}
	
	/**
	 * Returns the palette model
	 * 
	 * @return
	 */
	public PaletteModel paletteModel() {
		return paletteModel;
	}
	
	/**
	 * Sets the palette model.
	 * 
	 * @param pm
	 */
	public void paletteModel(PaletteModel pm) {
		// this may need synchronization
		paletteModel = pm;
		
		paletteModel.min = efData.minZ;
		paletteModel.max = efData.maxZ;
	}

	@Override
	protected void drawComponent(GLAutoDrawable drawable) {
		GL gl = drawable.getGL();
		
		List<Site> siteList = efData.siteList;
		List<Edge> edgeList = efData.edgeList;
		List<Triangle> triangleList = efData.triangleList;

		Color c;
		Site s;
		
		// draw edges
		for(Edge e : edgeList) {
			gl.glBegin(GL.GL_LINES);
				s = siteList.get(e.orgIndex);
				if(paletteModel.palette() != null) {
					c = paletteModel.getColor(s.z);
					gl.glColor3f(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f);
				}
				gl.glVertex3f(s.x, s.y, s.z);
				
				s = siteList.get(e.dstIndex);
				if(paletteModel.palette() != null) {
					c = paletteModel.getColor(s.z);
					gl.glColor3f(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f);
				}
				gl.glVertex3f(s.x, s.y, s.z);
			gl.glEnd();
		}
		
		if(showSurface) {
			// draw faces - be careful with the norms
			for(Triangle t : triangleList) {
				gl.glBegin(GL.GL_TRIANGLES);
					s = siteList.get(t.site1);
					if(paletteModel.palette() != null) {
						c = paletteModel.getColor(s.z);
						gl.glColor4f(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, opacity);
					}
					gl.glVertex3f(s.x, s.y, s.z);
					
					s = siteList.get(t.site2);
					if(paletteModel.palette() != null) {
						c = paletteModel.getColor(s.z);
						gl.glColor4f(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, opacity);
					}
					gl.glVertex3f(s.x, s.y, s.z);
	
					s = siteList.get(t.site3);
					if(paletteModel.palette() != null) {
						c = paletteModel.getColor(s.z);
						gl.glColor4f(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, opacity);
					}
					gl.glVertex3f(s.x, s.y, s.z);
				gl.glEnd();
			}
		}
		
	}
}